﻿using express.bttree;

namespace express.compiler;

public class ExprUtils
{
      public static Node toBtTree(SyntaxNode parent, Type klass) {
        if(parent.Type == SyntaxNodeType.Nodes) {
            List<SyntaxNode> childNodes = parent.ChildNodes;
            if(childNodes.Count > 1) {
                SyntaxNode opNode = childNodes[1];
                Node node;
                if(opNode.Type == SyntaxNodeType.Or) {
                    node = new OrNode();
                } else if(opNode.Type == SyntaxNodeType.And) {
                    node = new AndNode();
                } else {
                    throw new Exception("不能处理该节点，" + opNode.Type);
                }
                foreach (SyntaxNode childNode in childNodes) {
                    if(childNode.Type != SyntaxNodeType.Or && childNode.Type != SyntaxNodeType.And) {
                        node.Children.Add(toBtTree(childNode, klass));
                    }
                }
                return node;
            } else {
                return toBtTree(childNodes[0], klass);
            }
        } else if(parent.Type == SyntaxNodeType.Expr) {
            MethodInfo methodInfo = MethodInfo.convert(parent.ChildNodes);

            OpNode opNode = (OpNode)klass.Assembly.CreateInstance(klass.FullName);
            opNode.Method = methodInfo.MethodName;
            opNode.Params = methodInfo.Params;
            opNode.Op = methodInfo.Op;
            opNode.Value  = methodInfo.Result;
            return opNode;
        } else {
            throw new Exception("不处理该节点，" + parent.Type);
        }
    }

    public static Node convert(String scriptExpr, Type klass) {
        Tokenizer tokenizer = new Tokenizer(scriptExpr);
        List<String> tokens = tokenizer.Tokenize();
        Parser parser = new Parser(tokens);
        SyntaxNode syntaxNode = parser.parse();
        Node btNode = toBtTree(syntaxNode,klass);
        return btNode;
    }
}